package la.renzhen.rtpt.spring.boot.endpoint;

import la.renzhen.rtpt.config.ConfigurationSource;
import la.renzhen.rtpt.config.Reloadable;
import la.renzhen.rtpt.config.source.CachedConfigurationSource;
import la.renzhen.rtpt.config.source.MergeConfigurationSource;
import la.renzhen.rtpt.config.source.SpringConfigurationSource;
import la.renzhen.rtpt.spring.boot.RTPTProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
import org.springframework.boot.actuate.endpoint.mvc.HypermediaDisabled;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Collections;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * @author <a href="mailto:zhouhaichao@2008.sina.com">haiker</a>
 * @version 10/05/2018 5:07 PM
 */
@Slf4j
@ConfigurationProperties(prefix = "endpoints." + RTPTProperties.PREFIX)
public class RTPTMVCEndpoint extends EndpointMvcAdapter {

    /**
     * Create a new {@link EndpointMvcAdapter}.
     *
     * @param delegate the underlying {@link Endpoint} to adapt.
     */
    public RTPTMVCEndpoint(RTPTEndpoint delegate) {
        super(delegate);
    }

    @GetMapping("/sources")
    @ResponseBody
    @HypermediaDisabled
    public Object getAllSources() {
        RTPTEndpoint endpoint = (RTPTEndpoint) this.getDelegate();
        ConfigurationSource source = ((SpringConfigurationSource) endpoint.getSource()).getConfigurationSource();
        if (source instanceof CachedConfigurationSource) {
            source = ((CachedConfigurationSource) source).getConfigurationSource();
        }
        if (source instanceof MergeConfigurationSource) {
            return ((MergeConfigurationSource) source).getConfigurationSources()
                    .stream().map(ConfigurationSource::getClass)
                    .map(Class::getName).collect(Collectors.toList());
        } else {
            return Collections.singleton(source.getClass().getName());
        }
    }


    /**
     * 向外暴露刷新服务
     *
     * @param applicationToken 访问的X-APPLICATION-TOKEN 此项参数会在启动时自动设置到注册中心
     * @param userAgent        用户访问UserAgent属性
     * @return 刷新结果
     */
    @RequestMapping("/refresh")
    @ResponseBody
    @HypermediaDisabled
    public Object refresh(
            @RequestHeader(value = "X-APPLICATION-TOKEN", required = false) String applicationToken,
            @RequestHeader(value = "User-Agent") String userAgent
    ) {
        if (!StringUtils.hasText(applicationToken)) {
            applicationToken = userAgent;
        }
        log.info("请求刷新: {}", applicationToken);

        ConfigurationSource configurationSource = ((RTPTEndpoint) this.getDelegate()).getSource();
        if (configurationSource instanceof Reloadable) {
            ((Reloadable) configurationSource).reload();
        }
        return ResponseEntity.ok().build();
    }
}
